/*
* Iterators.h
* iphone-gl-app
*
* Created by John Ryland on 15/06/09.
* Copyright 2009 InvertedLogic. All rights reserved.
*
*/
#ifndef ITERATORS_H
#define ITERATORS_H
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Debug.h"
#ifdef DEBUG
#define BOUNDS_CHECKING 1
#endif
// Syntactic sugar, yummy!
#define foreach(item, items) /* Iterate for each item in the collection of items. 'item' can refer to the name of an */ \
/* existing variable, or it can declare a new variable with the type plus name declared */ \
/* in the usual manner. 'items' should be an object of a type that subclasses Iterable. */ \
/* 'item' should be of a type that corresponds to the type 'items' is a collection of. */ \
for (int i = 0, loop = 0, cnt = items.count(); i < cnt; i++, loop = 0) \
/* The next for statement loops only once, it is a clever way to have 'item' expanded */ \
/* by the preprocessor. The block after the foreach statement will then be executed */ \
/* with 'item' in the scope and no need to worry about how to handle encapuslating */ \
/* braces for an outter block using the preprocessor to declare a new variables. */ \
for (item = items[i]; loop < 1; loop++)
// Interfaces
template<typename T>
class Iterable
{
public:
Iterable();
Iterable(const Iterable<T> &cpy);
virtual ~Iterable();
const Iterable<T> &operator=(const Iterable<T> &cpy);
void copy(const Iterable<T> ©);
int count() const;
operator const T *() const;
T &operator[](int);
const T &operator[](int) const;
protected:
T *items;
int cnt;
};
template<typename T>
class List : public Iterable<T>
{
public:
const List<T> &operator+=(T);
const List<T> &operator+=(const List<T> &);
};
template<typename T>
class Dict : public Iterable<T>
{
public:
Dict();
virtual ~Dict();
void append(const char *key, T item);
void remove(const char *key);
const T &find(const char *key);
protected:
char **keys;
};
template<typename T>
class Map : public Dict<T>
{
public:
T &operator[](const char *key);
/* expose the base class operator functions */
T &operator[](int i) { return (*this)[i]; }
const T &operator[](int i) const { return (*this)[i]; }
};
template<typename T>
class MultiMap : public Dict<T>
{
public:
List<T> &operator[](const char *key);
/* expose the base class operator functions */
T &operator[](int i) { return (*(Iterable<T>*)this)[i]; }
//const T &operator[](int i) const { return (*(Iterable<T>*)this)[i]; }
};
// Implementations
template<typename T>
Iterable<T>::Iterable() : items(0), cnt(0)
{
}
template<typename T>
Iterable<T>::Iterable(const Iterable<T> &cpy) : items(0)
{
copy(cpy);
}
template<typename T>
Iterable<T>::~Iterable()
{
if (items)
free(items);
}
template<typename T>
const Iterable<T> &Iterable<T>::operator=(const Iterable<T> &cpy)
{
copy(cpy);
return *this;
}
template<typename T>
void Iterable<T>::copy(const Iterable<T> ©)
{
items = (T*)realloc(items, sizeof(T) * copy.cnt);
memcpy(items, copy.items, sizeof(T) * copy.cnt);
cnt = copy.cnt;
}
template<typename T>
int Iterable<T>::count() const
{
return cnt;
}
template<typename T>
Iterable<T>::operator const T *() const
{
return items;
}
template<typename T>
T &Iterable<T>::operator[](int x)
{
if (items && cnt > x)
return items[x];
#ifdef BOUNDS_CHECKING
DebugMessage::error("Access past end of the array\n");
#endif
static T ret;
return ret;
}
template<typename T>
const T &Iterable<T>::operator[](int x) const
{
if (items && cnt > x)
return items[x];
#ifdef BOUNDS_CHECKING
DebugMessage::error("Access past end of the array\n");
#endif
static T ret;
return ret;
}
template<typename T>
const List<T> &List<T>::operator+=(T item)
{
this->cnt++;
this->items = (T *)realloc(this->items, sizeof(T) * this->cnt);
this->items[this->cnt - 1] = item;
return *this;
}
template<typename T>
const List<T> &List<T>::operator+=(const List<T> &others)
{
int pos = this->cnt;
this->cnt += others.cnt;
this->items = (T *)realloc(this->items, sizeof(T) * this->cnt);
for (int i = 0; i < others.cnt; i++)
this->items[pos + i] = others.items[i];
return *this;
}
template<typename T>
Dict<T>::Dict() : Iterable<T>()
{
keys = 0;
}
template<typename T>
Dict<T>::~Dict()
{
if (keys)
for (int i = 0; i < this->cnt; i++)
free(keys[i]);
free(keys);
}
template<typename T>
void Dict<T>::append(const char *key, T item)
{
this->cnt++;
keys = (char **)realloc(keys, sizeof(char *) * this->cnt);
this->items = (T*)realloc(this->items, sizeof(T) * this->cnt);
keys[this->cnt - 1] = strdup(key);
this->items[this->cnt - 1] = item;
}
template<typename T>
void Dict<T>::remove(const char *key)
{
for (int i = 0; i < this->cnt; i++)
if (!strcmp(key, this->keys[i])) {
free(this->keys[i]);
this->cnt--;
for (; i < this->cnt; i++) {
this->items[i] = this->items[i+1];
this->keys[i] = this->keys[i+1];
}
this->keys = (char **)realloc(this->keys, sizeof(char *) * this->cnt);
this->items = (T*)realloc(this->items, sizeof(T) * this->cnt);
return;
}
}
template<typename T>
const T &Dict<T>::find(const char *key)
{
for (int i = 0; i < this->cnt; i++)
if (!strcmp(key, this->keys[i]))
return this->items[i];
static T ret;
T r;
ret = r;
return ret;
}
template<typename T>
T &Map<T>::operator[](const char *key)
{
for (int i = 0; i < this->cnt; i++)
if (!strcmp(key,this->keys[i]))
return this->items[i];
static T ret;
return ret;
}
template<typename T>
List<T> &MultiMap<T>::operator[](const char *key)
{
static List<T> ret;
List<T> empty;
ret = empty;
for (int i = 0; i < this->cnt; i++)
if (!strcmp(key,this->keys[i]))
ret += this->items[i];
return ret;
}
#endif // ITERATORS_H